#include "behaviortree_cpp_v3/bt_factory.h"
#include "behaviortree_cpp_v3/actions/script_node.h"
#include "behaviortree_cpp_v3/actions/script_condition.h"

#include "behaviortree_cpp_v3/loggers/bt_cout_logger.h"
#include "behaviortree_cpp_v3/loggers/bt_minitrace_logger.h"
#include "behaviortree_cpp_v3/loggers/bt_file_logger.h"
#include "sol/sol.hpp"
#include <fstream>
#include <string>

using namespace BT;

/** Behavior Tree are used to create a logic to decide what
 * to "do" and when. For this reason, our main building blocks are
 * Actions and Conditions.
 *
 * In this tutorial, we will learn how to create custom ActionNodes.
 * It is important to remember that NodeTree are just a way to
 * invoke callbacks (called tick() ). These callbacks are implemented by the user.
 */

static const char* xml_text = R"(
 <root main_tree_to_execute = "MainTree" >
     <BehaviorTree ID="MainTree">
        <ReactiveSequence name="root_fallback">
              <Delay delay_msec="1000">
                <Script name="script_node" path="C:/Users/XF/Desktop/lua_test.lua"/>
              </Delay>
              <Idle name="idle_node" msec="2000"/>
        </ReactiveSequence>
     </BehaviorTree>
 </root>
 )";

#if 0
class IdleNode : public BT::StatefulActionNode
{
public:
  IdleNode(const std::string& name, const BT::NodeConfiguration& config)
    : BT::StatefulActionNode(name, config)
  {}

  static BT::PortsList providedPorts()
  {
      // amount of milliseconds that we want to sleep
      return{ BT::InputPort<int>("msec") };
  }

  NodeStatus onStart() override
  {
      int msec = 0;
      getInput("msec", msec);
      if( msec <= 0 )
      {
          // no need to go into the RUNNING state
          return NodeStatus::SUCCESS;
      }
      else {
          using namespace std::chrono;
          // once the deadline is reached, we will return SUCCESS.
          deadline_ = system_clock::now() + milliseconds(msec);
          return NodeStatus::RUNNING;
      }
  }

  /// method invoked by an action in the RUNNING state.
  NodeStatus onRunning() override
  {
      return NodeStatus::RUNNING;
      if ( std::chrono::system_clock::now() >= deadline_ )
      {
          return NodeStatus::SUCCESS;
      }
      else {
          return NodeStatus::RUNNING;
      }
  }

  void onHalted() override
  {
      std::cout << "SleepNode interrupted" << std::endl;
  }

private:
  std::chrono::system_clock::time_point deadline_;
};
#endif


int main()
{
    // We use the BehaviorTreeFactory to register our custom nodes

      BehaviorTreeFactory factory;

      //factory.registerNodeType<IdleNode>("Idle");

#if 0
      SimpleDecoratorNode::TickFunctor func = [](NodeStatus rStatus, TreeNode&)->NodeStatus
      {
          return NodeStatus::RUNNING;
          if(rStatus == NodeStatus::RUNNING || rStatus == NodeStatus::FAILURE)
          {
              return rStatus;
          }
          else if(rStatus == NodeStatus::SUCCESS)
          {
              return NodeStatus::FAILURE;
          }
          else
          {
              throw LogicError("A child node must never return IDLE");
          }
      };

      factory.registerSimpleDecorator("FaultDec",func,{});
#endif
      auto tree = factory.createTreeFromFile("C:/Users/XF/Desktop/BTTest.xml");
      //auto tree = factory.createTreeFromText(xml_text);

      StdCoutLogger logger_cout(tree);
      tree.tickRootWhileRunning();

    return 0;
}

